package a1;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.colorchooser.AbstractColorChooserPanel;

public class View extends JFrame implements ActionListener, FocusListener, PropertyChangeListener {
	
	/**
	 * Needed as JFrame is {@link Serializable}.
	 */
	private static final long serialVersionUID = -8549865004512092307L;
	
	private Model m;						// the passed Model to this View

	// Menu Components
	private JMenuBar menuBar;		// The default JMenuBar for the application
	
	private JMenu fileMenu;			// The File JMenu
	private JMenu helpMenu;			// The Help JMenu
	private JMenu settingsMenu;		// the Settings JMenu
	private JMenu colorModeMenu; 	// to switch between RGB mode and HEX mode
	private JMenu grayscaleModeMenu;// to select a grayscale mode (average/luminosity/etc)
	
	private JMenuItem addItem; 		// This JMenuItem allows the user to add another CSRB to the panel.
									// This new JTextField will allow the user to select one more colour
	private JMenuItem removeItem; 	// This JMenuItem allows the user to remove a CSRB from the panel.
	private JMenuItem exitItem;		// This JMenuItem will exit the application
	private JMenuItem aboutItem;	// This JMenuItem will allow the user to see information about the developers
	private JMenuItem aboutGrayscaleItem;
	
	private JRadioButtonMenuItem rgbRadio;
	private JRadioButtonMenuItem hexRadio;
	private JRadioButtonMenuItem averageRadio;
	private JRadioButtonMenuItem lightnessRadio;
	private JRadioButtonMenuItem luminosityRadio;
	
	// Toolbar Buttons
	private JButton addButton;
	private JButton removeButton;
	
	// Panels
	private final JPanel mainPanel; 		// This JPanel will be the main container for the application
	private final JPanel colorChooserPanel;
	private final JPanel rightPanel;		// This JPanel holds all the JTextFields and the overrideBox.
											// It sits on the right hand side of the screen.
	
	// The Main JColorChooser which will allows a user to select a colour to be displayed in a Custom JTextField
	private JColorChooser colorChooser;
	private Border colorChooserBorder;
	
	// CheckBoxes
	// This JCheckBox will allow the user to override the pre-calculated JColorChooser selection
	// even though it is probably unsafe to do so. 
	//private static JCheckBox overrideBox; 	
	// Turns out it's complicated as hell to implement, and not worth it.
	
	private ButtonGroup radioGroup;
	private ButtonGroup menuColorGroup;
	private ButtonGroup menuGrayscaleGroup;
	private List<JRadioButton> radioButtonList;	
	
	/**
	 * Main Constructor.
	 */
	public View(Model m) {
		

		
		super(Constants.WINDOW_TEXT); 		// Set title for the View window
		
		this.m = m;
		
		try {	
		// Set OS look and feel
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		}
		catch (Exception e)
		{} 	// If we cannot set the System look and feel, the window will default to the Java LaF
		
		this.setJMenuBar(this.createMenu()); 	// Creates a JMenuBar for our View
		
		// Setup the main panel
		this.mainPanel = new JPanel();	
		// Set Layout to BoxLayout to align the colorChooser and JTextFields vertically
		this.mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.LINE_AXIS));	
		
		// Setup the left panel, which will hold our Color Chooser
		this.colorChooserPanel = new JPanel();
		// Give the colorChooserPanel a border with a title
		// We need to keep track of the title as it will change when a user changes colours.
		this.colorChooserBorder = new TitledBorder(BorderFactory.createEtchedBorder(), Constants.COLOR_ONE);
		this.colorChooserPanel.setBorder(colorChooserBorder);
		
		this.colorChooser = this.buildColorChooser();	// build the JColorChooser with a custom panel
		
		this.colorChooserPanel.add(this.colorChooser);	// add our custom Colour Chooser to the panel
		//this.colorChooserPanel.addPropertyChangeListener(Constants.TEXT_UPDATE_EVENT, this);

		
		this.rightPanel = this.buildRightPanel();	// build the right panel, which will hold our
														// JTextFields with the users colours 
		// add the panels to each side of the main panel
		this.mainPanel.add(this.colorChooserPanel);
		this.mainPanel.add(this.rightPanel);
		
		// add the main panel to the content pane
		this.add(buildToolbar(), BorderLayout.PAGE_START);
		this.add(this.mainPanel);
	}
	
	private JToolBar buildToolbar() {
		// TODO uses a + sign for add color. Eventually, it will use a graphic.
		JToolBar result = new JToolBar();
		
		this.addButton = new JButton("+");	
		this.addButton.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		this.addButton.setFocusable(false);
		this.addButton.setToolTipText(Constants.ADD_TEXT);		
		this.addButton.addActionListener(this);
		
		this.removeButton = new JButton(" - ");		
		this.removeButton.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		this.removeButton.setFocusable(false);
		this.removeButton.setToolTipText(Constants.REMOVE_TEXT);
		this.removeButton.addActionListener(this);
		
		result.add(this.addButton);
		result.add(this.removeButton);
		result.setFloatable(false);
		
		return result;
		
	}
	
	private JPanel buildRightPanel() {
		// TODO need to document
		JPanel result = new JPanel();
		
		// Set to BoxLayout to align the JTextFields vertically in one column, 
		// we add one to account for the override checkbox field.
		result.setLayout(new GridLayout(7,2)); 
	
		//overrideBox = new JCheckBox(Constants.OVERRIDE_TEXT); 	// Instantiate the Override Colour JCheckBox

		// add override checkbox and one initial color JTextField
		//result.add(overrideBox);
		// Hack to get the width of the CSRB's to be larger, to allow for the users input
		// also conveniently puts the default CSRBs in the center, which looks nice
		// this hack is win-win in my books :-)
		result.add(Box.createHorizontalStrut(Constants.CSRB_WIDTH));
		result.add(Box.createHorizontalStrut(Constants.CSRB_WIDTH));
		
		this.radioButtonList = new ArrayList<JRadioButton>();
		this.radioGroup = new ButtonGroup();
		
		
		for (int i = 0; i < Constants.INITIAL_COLOR_CHOICES; i++) {
			JRadioButton button = createRadioButton(this.radioButtonList, this.radioGroup);
			//add the listener for each button created. Must remember to add this
			//again when more buttons are added.
			//button.addFocusListener(listener);
			
			Color c = new Color(Color.black.getRGB()) {
				/**
				 * Needed since color is serializable.
				 */
				private static final long serialVersionUID = 1L;

				@Override
				public Color brighter() {
					return new Color(this.getRed() + Constants.COLOR_PERCEPTION_DISTANCE,
									this.getGreen() + Constants.COLOR_PERCEPTION_DISTANCE,
									this.getBlue() + Constants.COLOR_PERCEPTION_DISTANCE);
				}
			};
			
			if (i == 0)
			{	// set the first radio button to selected so the user knows that is their active colour.
				button.setSelected(true);	
				((ColorSelectionRadioButton) button).setColor(m.getMode(), c);
			} else {
				((ColorSelectionRadioButton) button).setColor(m.getMode(), c.brighter());
			}
			
			result.add(button);
		}
		
		return result;
	}
	/**
	 * Creates a RadioButton (a ColorSelectionRadioButton in this case), and adds it to the specified List and Group
	 * @param group the group to add this component to
	 * @param list the List to add this component to
	 * @return the created radio button
	 */
	private JRadioButton createRadioButton(List<JRadioButton> list, ButtonGroup group) {
		// TODO Auto-generated method stub
		JRadioButton button = new ColorSelectionRadioButton(m);
		
		button.addFocusListener(this);			// used to capture external focus events
		button.addPropertyChangeListener(this); // used to capture internal focus events
		
		list.add(button);
		group.add(button);
		
		button.setSelected(false);
		//button.setSize(Constants.CSRB_WIDTH, button.getPreferredSize().height);
		
		return button;
	}

	/**
	 * Builds a JColorChooser for our View
	*/
	private JColorChooser buildColorChooser() {
		// TODO Auto-generated method stub
		
		JColorChooser result = new JColorChooser() {
			/**
			 * Needed since JColorChooser is serialized
			 */
			private static final long serialVersionUID = 5684561954460709902L;

			@Override
			public void setColor(Color c) {
				((RGBSliderChooserPanel) this.getChooserPanels()[0]).setColor(c);
			}
		};	// Instantiate JColorChooser, let setColor set the color in the RGBSCP.java
		
		AbstractColorChooserPanel[] panel = new AbstractColorChooserPanel[1];
		panel[0] = new RGBSliderChooserPanel(); 
		panel[0].addPropertyChangeListener(Constants.TEXT_UPDATE_EVENT, this);
		result.setChooserPanels(panel);	
		
		result.setPreviewPanel(new JPanel());			// remove Preview Panel
		
		return result;
	}

	/**
	 * This function creates and returns a JMenuBar. 
	 * The Menu consists of a File JMenu and a Help JMenu.
	 * Inside the File JMenu we have an Add Colour JMenuItem and an Exit JMenuItem.
	 * Inside the Help JMenu we have an About JMenuItem. 
	 */
	private JMenuBar createMenu() {
		// Instantiate all menu bars and items
		this.menuBar = new JMenuBar();
		this.menuColorGroup = new ButtonGroup();
		this.menuGrayscaleGroup = new ButtonGroup();
		
		this.fileMenu = new JMenu(Constants.FILE_TEXT);
		this.settingsMenu = new JMenu(Constants.SETTINGS_TEXT);
		this.colorModeMenu = new JMenu(Constants.COLOR_DISPLAY_TEXT);
		this.grayscaleModeMenu = new JMenu(Constants.GRAYSCALE_MODE_TEXT);
		this.helpMenu = new JMenu(Constants.HELP_TEXT);
		
		this.addItem = new JMenuItem(Constants.ADD_TEXT);
		this.addItem.addActionListener(this);		
		this.removeItem = new JMenuItem(Constants.REMOVE_TEXT);
		this.removeItem.addActionListener(this);
		
		this.rgbRadio = new JRadioButtonMenuItem(Constants.RGB_TEXT);
		this.rgbRadio.addActionListener(this);
		this.hexRadio = new JRadioButtonMenuItem(Constants.HEX_TEXT);
		this.hexRadio.addActionListener(this);
		
		this.rgbRadio.setSelected(true);
		this.menuColorGroup.add(this.rgbRadio);
		this.menuColorGroup.add(this.hexRadio);
		
		this.averageRadio = new JRadioButtonMenuItem(Constants.AVERAGE_TEXT);
		this.averageRadio.addActionListener(this);
		this.lightnessRadio =  new JRadioButtonMenuItem(Constants.LIGHTNESS_TEXT);
		this.lightnessRadio.addActionListener(this);
		this.luminosityRadio =  new JRadioButtonMenuItem(Constants.LUMINOSITY_TEXT);
		this.luminosityRadio.addActionListener(this);
		
		this.averageRadio.setSelected(true);
		this.menuGrayscaleGroup.add(this.averageRadio);
		this.menuGrayscaleGroup.add(this.lightnessRadio);
		this.menuGrayscaleGroup.add(this.luminosityRadio);
		
		this.exitItem = new JMenuItem(Constants.EXIT_TEXT);
		this.exitItem.addActionListener(this);
		
		this.aboutItem = new JMenuItem(Constants.ABOUT_TEXT);
		this.aboutItem.addActionListener(this);
		
		this.aboutGrayscaleItem = new JMenuItem(Constants.ABOUT_GRAYSCALE_MODES_TEXT);
		this.aboutGrayscaleItem.addActionListener(this);
		
		// Now we add all the JMenuItems to the menu
		// Add the JMenuItems to the respective JMenu's
		this.fileMenu.add(this.addItem);
		this.fileMenu.add(this.removeItem);
		this.fileMenu.add(this.exitItem);
		
		this.colorModeMenu.add(this.rgbRadio);
		this.colorModeMenu.add(this.hexRadio);
		
		this.grayscaleModeMenu.add(this.averageRadio);
		this.grayscaleModeMenu.add(this.lightnessRadio);
		this.grayscaleModeMenu.add(this.luminosityRadio);
		
		this.settingsMenu.add(this.colorModeMenu);
		this.settingsMenu.addSeparator();
		this.settingsMenu.add(this.grayscaleModeMenu);
		
		this.helpMenu.add(this.aboutItem);
		this.helpMenu.add(this.aboutGrayscaleItem);
		
		// Add the JMenu's to the JMenuBar
		this.menuBar.add(this.fileMenu);
		this.menuBar.add(this.settingsMenu);
		this.menuBar.add(this.helpMenu);
		
		return menuBar;		// return the JMenuBar so the caller can add it
		
	}

	/**
	 * Performs actions for specific targets
	 */
	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		Object source = e.getSource();
		
		if ((source == this.addItem) || (source == this.addButton)) {
			// user wants to add a CSRB
			if (this.radioButtonList.size() < Constants.MAX_COLOR_FIELDS) {
				// TODO make unique colour for CSRB
				this.rightPanel.add(this.addNewRadio());
				this.revalidate();
				this.repaint();
				this.pack();
			}
		} else if ((source == this.removeItem) || (source == this.removeButton)) {
			// user wants to remove the last Radio Button
			if (this.radioButtonList.size() > Constants.INITIAL_COLOR_CHOICES) {
				JRadioButton b = this.radioButtonList.remove(this.radioButtonList.size() - 1);
				this.rightPanel.remove(b);
				this.revalidate();
				this.repaint();
				this.pack();
			}
		} else if (source == this.aboutItem) {
			// show about screen
			this.showAbout();
		} else if (source == this.aboutGrayscaleItem) {
			this.showAboutGrayscale();
		} else if (source == this.exitItem) {
			// user wants to exit
			this.dispose();
			System.exit(0);
		} else if (source instanceof JRadioButtonMenuItem) {
			this.handleMenuEvent((JRadioButtonMenuItem) source);
		} 
		
	}
	
	private ColorSelectionRadioButton addNewRadio() {
		// TODO Auto-generated method stub
		ColorSelectionRadioButton b = (ColorSelectionRadioButton) this.createRadioButton(this.radioButtonList, this.radioGroup);
		Color c = Color.black;
		Color[] colors = new Color[this.radioButtonList.size()];
		for (int i = 0; i < this.radioButtonList.size(); i++) {
			colors[i] = Model.toGrayscale(((ColorSelectionRadioButton) this.radioButtonList.get(i)).getColor(), this.m.getMode());
			System.out.println(colors[i]);
		}
		
		System.out.println("All colors: ");
		for (int i = 0; i < colors.length - 1; i++) {
			System.out.println(colors[i]);
		}
		
		System.out.println("First color is:" + colors[0]);
		System.out.println();
		
		while(!Model.isColorUnique(c, colors)) {
			c = Model.makeBrighter(c);
		}
		
		b.setColor(this.m.getMode(), c); 
		return b;		
	}

	private void handleMenuEvent(JRadioButtonMenuItem source) {
		source.setSelected(true);
		// TODO Auto-generated method stub
		if (source == this.rgbRadio) {
			this.m.setMode(Constants.RGB_MODE);
			this.updateTextFields(this.radioButtonList, Constants.RGB_MODE);
		} else if (source == this.hexRadio) {
			this.m.setMode(Constants.HEX_MODE);
			this.updateTextFields(this.radioButtonList, Constants.HEX_MODE);
		} else if (source == this.averageRadio) {
			this.m.setGrayscaleMode(Constants.AVERAGE_MODE);
		} else if (source == this.lightnessRadio) {
			this.m.setGrayscaleMode(Constants.LIGHTNESS_MODE);
		} else if (source == this.luminosityRadio) {
			this.m.setGrayscaleMode(Constants.LUMINOSITY_MODE);
		}
		/*
		System.out.print("Current Color Mode is ");
		switch(this.m.getMode()) {
			case 1: System.out.println("RGB"); break;
			case 2: System.out.println("HEX"); break;
		}
		
		System.out.print("Current Grayscale Mode is ");
		switch(this.m.getGrayscaleMode()) {
			case 1: System.out.println("AVERAGE"); break;
			case 2: System.out.println("LIGHTNESS"); break;
			case 3: System.out.println("LUM"); break;
		}
		*/
		
	}

	private void updateTextFields(List<JRadioButton> list, int mode) {
		for (int i = 0; i < list.size(); i++) {
			list.get(i).setText(
					Model.makeText(	mode, 
									((ColorSelectionRadioButton) list.get(i)).getColor())
									);
		}
		
	}

	/*
	public static Dimension getOverrideCheckBoxSize() {
		return overrideBox.getPreferredSize();
	}*/
	
	/**
	 * Returns the currently selected radio button
	 * @return  the currently selected radio button
	 * @throws IllegalStateException if RadioButton's index is not found
	 */
	public int getCurrentlySelectedRadioButton() throws IllegalStateException {
		int i = 0;
		for (; i < this.radioButtonList.size(); i++) {
			if (this.radioButtonList.get(i).isSelected() == true)
				return i;
		}
		
		throw new IllegalStateException(Constants.ILLEGAL_RADIO_BUTTON_STATE);
	}
	
	/**
	 * updates the current radio button with the specified color
	 * @param newColor the new color for this CSRB
	 * @throws IllegalStateException if the button can't be found
	 */
	public void updateCurrentRadioButton(Color newColor) throws IllegalStateException {
		int i = 0;
		ColorSelectionRadioButton button = null;
		for (; i < this.radioButtonList.size(); i++) {
			if (this.radioButtonList.get(i).isSelected() == true) 
				button = ((ColorSelectionRadioButton) this.radioButtonList.get(i));
			// List.get() is O(1), so no need to make temporary variables
		}
		
		if (button == null)
			throw new IllegalStateException(Constants.ILLEGAL_RADIO_BUTTON_STATE);
		
		String text; 
		
		if (m.getMode() == Constants.RGB_MODE) {
			text = Model.makeRGBText(newColor);
			
		} else if (m.getMode() == Constants.HEX_MODE) {
			text = Model.makeHexText(newColor);
		} else { text = "Error"; }
		button.setColorAndText(newColor, text);

	}

	/**
	 * Handles propertyChangeEvents between the CSRB, the View and the RGBSCP
	 */
	@Override	
	public void propertyChange(PropertyChangeEvent evt) {
		//System.out.println("A PropertyChangeEvent was received: " + evt.getPropertyName());
		
		if (evt.getPropertyName().equals(Constants.TEXT_UPDATE_EVENT)) {
			// A TEXT_UPDATE_EVENT occurs when the RGBSCP wants to update the 
			// JTextField in CSRB
			RGBSliderChooserPanel panel = (RGBSliderChooserPanel) this.colorChooser.getChooserPanels()[0];
			this.updateCurrentRadioButton(panel.getColor());
		} else if (evt.getPropertyName().equals(Constants.ASK_FOCUS_EVENT)) {
			// An ASK_FOCUS_EVENT means the JTextField in CSRB just gained focus, we
			// want to display its color in the RGBSCP's preview panel, and set the
			// state to selected
			ColorSelectionRadioButton b = (ColorSelectionRadioButton) evt.getSource();
			b.setSelected(true);
			this.colorChooser.setColor(b.getColor());
			
			/*
			for (int i = 0; i < this.radioButtonList.size(); i++) {
				if (b == this.radioButtonList.get(i)) {
					// we have found the button that wanted focus, let's give it focus
					System.out.println("Button " + i + " requested focus: ");
					//b.requestFocusInWindow();
					System.out.println("Color for button " + i + " is " + b.getColor().toString());
					this.colorChooser.setColor(b.getColor());
					b.setSelected(true);
				}
			}*/
			//System.out.println(evt.getSource() + " requested focus");
		} else if (evt.getPropertyName().equals(Constants.COLOR_PARSE_ERROR)) {
			this.showError(Constants.ILLEGAL_COLOR_TITLE, Constants.ILLEGAL_COLOR);
		} else if (evt.getPropertyName().equals(Constants.TEXTFIELD_LOST_FOCUS_EVENT)) {
			// A TEXTFIELD_LOST_FOCUS_EVENT means the JTextField just lost focus 
			// we want to check to see if its new Color clashes (is similar to) another
			// Color in our radioButtonList
			/*ColorSelectionRadioButton b = (ColorSelectionRadioButton) evt.getSource();
			System.out.println("Color for the button that just lost focus: " + b.getColor());
			Color allColors[] = new Color[this.radioButtonList.size()-1];
			for (int i = 0; i < this.radioButtonList.size(); i++) {
				if (this.radioButtonList.get(i) != b)
				allColors[i] = Model.toGrayscale(((ColorSelectionRadioButton) this.radioButtonList.get(i)).getColor(), m.getMode());
			}
			if (!Model.isColorUnique(Model.toGrayscale(b.getColor(), m.getMode()), allColors)) {
				this.showError("Color Clash", "This color clashes with a previously specified color");
			}*/
			/*
			ColorSelectionRadioButton b = (ColorSelectionRadioButton) evt.getSource();
			
			// set the text for the old button depending on the model
			if (m.getMode() == Constants.RGB_MODE) {
				// set RGB Value in the textField
				b.setText(Model.makeRGBText(b.getColor()));
			} else if (m.getMode() == Constants.HEX_MODE) {
				// set HEX value in textField
				b.setText(Model.makeHexText(b.getColor()));
			} else {
				try {
					throw new Exception(Constants.ILLEGAL_COLOR_MODE + m.getMode());
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}*/
		} // end TEXTFIELD_LOST_FOCUS_EVENT code

	}
	
	/** 
	 * Displays an error message
	 * @param error the error to display
	 */
	public void showError(String error) {
		JOptionPane.showMessageDialog(this, error, "Error", JOptionPane.ERROR_MESSAGE);
	}
	
	/**
	 * Display an error message, gives window the specified title
	 * @param title title of the error window
	 * @param error the error message to display
	 */
	public void showError(String title, String error) {
		JOptionPane.showMessageDialog(this, error, title, JOptionPane.ERROR_MESSAGE);
	}
	
	/** 
	 * Shows Abou the Authors.
	 */
	public void showAbout() {
		JOptionPane.showMessageDialog(this, Constants.ABOUT_AUTHORS, Constants.ABOUT_TEXT, JOptionPane.INFORMATION_MESSAGE);
	}
	
	/** 
	 * Shows About Grayscale Modes.
	 */
	public void showAboutGrayscale() {
		//JOptionPane.showMessageDialog(this, "create a dialog showing the different grayscale modes, use pics from http://www.johndcook.com/blog/2009/08/24/algorithms-convert-color-grayscale/", "About Grayscale Modes", JOptionPane.INFORMATION_MESSAGE);
		try {
			AboutGrayscale a = new AboutGrayscale();
			a.setLocationRelativeTo(this);
			a.setVisible(true);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * Updates the previewPanel in the RGBSCP to the specified color
	 * @param r red value
	 * @param g green value
	 * @param b blue value
	 */
	public void updateColorChooser(int r, int g, int b)
	{
		this.colorChooser.setColor(r, g, b);
	}

	/**
	 * Handles focus lost events 
	 */
	@Override
	public void focusLost(FocusEvent e) 
	{ 
		// overridden method from implementing FocusListener
		System.out.println("Focus Lost: " + e.getSource().getClass());
		Object source = e.getSource(); 
		if (source instanceof ColorSelectionRadioButton)
		{	// we know for sure now source is a CSRB
			ColorSelectionRadioButton b = (ColorSelectionRadioButton) source;
			System.out.println("The text of this CSRB (before parsing) was: " + b.getText());
			if (b.parseInput(m.getMode()))
			{   
				//System.out.println("parsing style=" +m.getMode()+ " parseText returns: " +Model.parseText(m.getMode(), b.getText()).toString());
				//((RGBSliderChooserPanel) this.colorChooser.getChooserPanels()[0]).setColor(Model.parseText(m.getMode(), b.getText()));
			}
			else
			{
				showError("Invalid color!");
				b.setText("0,0,0"); // clear text from JTextField
				updateColorChooser(0,0,0);
				b.requestFocusInWindow();
			}
		}
		// indicate an error and set focus
	}
	
	/**
	 * handles focus gained events
	 */
	@Override
	public void focusGained(FocusEvent e) {
		Object source = e.getSource();
		System.out.println(source.getClass() + " requested focus.");
		if (source instanceof ColorSelectionRadioButton) {
			// if a CSRB wants focus, we set the previewPanel to display the CSRB's color
			ColorSelectionRadioButton b = (ColorSelectionRadioButton) source;
			b.requestFocusInWindow();
			//((RGBSliderChooserPanel) this.colorChooser.getChooserPanels()[0]).setColor(Model.parseText(m.getMode(), b.getText()));
		}
	}
}
